<template>
  <div class="container-item-upload">
    <draggable :list="list" @update="datadragEnd">
      <div v-for="(element,index) in list " :key="index" class="item-upload">
        <el-tag class="item-p" size="mini">{{ index +1 }}p</el-tag>
        <i class="item-music-icon" />
        <div class="item-info">
          <span class="item-title">{{ element.name }}</span>
          <el-progress class="item-progress" :percentage="element.progress" />
          <div class="other-info">
            <span class="total-size">{{ element.size | numberFormatter(2) }}</span>
          </div>
        </div>
        <i v-if="element.isComplete===false" class="item-reupload el-icon-refresh-right" @click="saveUploadHandler(element)"> <span style="font-size:12px">上传出错请重试</span></i>
        <i class="item-delete el-icon-delete" @click="deleteAudioResource(element,index)" />
        <el-popover width="400" placement="bottom-end">
          <el-form label-position="left" label-width="80px" size="mini">
            <el-form-item label="标题">
              <el-input v-model="element.name" clearable type="text" />
            </el-form-item>
            <el-form-item>
              <el-button :loading="isEdit" style="float:right" type="primary" @click="editInfoHandler(element)">确定</el-button>
            </el-form-item>
          </el-form>
          <i slot="reference" class="item-edit el-icon-edit"> 编辑信息 </i>
        </el-popover>
      </div>
    </draggable>
    <div class="item-upload-btn el-icon-plus"> 上传音频
      <input class="item-upload-input" type="file" accept=".mp3, .wav, .ogg" @change="checkFileHandler">
    </div>
  </div>
</template>

<script>
// api
import {
  createAudioResource,
  sortAudioResource,
  editAudioResource,
  deleteAudioResource
} from '@/api/mivawork/audio.js';
// item
import draggable from 'vuedraggable';
// utils
import generateOSS from '@/utils/upload_handler_miva';
import CryptoJS from 'crypto-js';

export default {
  components: { draggable },
  props: {
    aid: {
      type: [String, Number],
      required: true
    },
    value: {
      type: Array,
      default() {
        return [];
      }
    }
  },
  data() {
    return {
      isEdit: false,
      uploading: [],
      list: []
    };
  },
  watch: {
    list(val) {
      this.$emit('getResourceNum', val.length);
    }
  },
  created() {
    this.resetList();
  },
  destroyed() {
    for (const element of this.list) {
      if (element.ossClinet) {
        element.ossClinet.cancel();
      }
    }
  },
  methods: {
    resetList() {
      // 排序列表
      const arr = [];
      for (const audio of this.value) {
        const buffer = audio.store_resource;
        buffer.progress = 100;
        buffer.p = audio.p;
        buffer.id = audio.id;
        buffer.sid = audio.sid;
        buffer.isComplete = true;
        arr.push(buffer);
      }
      this.list = this.list.concat(arr).sort((a, b) => {
        return a.p - b.p;
      });
    },
    async datadragEnd(e) {
      // 拖动重新排序
      const sortData = [];
      for (const key in this.list) {
        const nowData = this.list[key];
        nowData.p = Number(key) + 1;
        sortData.push({
          id: nowData.id,
          p: nowData.p
        });
      }
      const { code } = await sortAudioResource({ sortData });
      if (code !== 200) {
        this.$message.error('排序出错,请重试');
      }
    },
    async deleteAudioResource(element, index) {
      const id = element.id;
      if (!id) {
        element.ossClinet.cancel();
        this.list.splice(index, 1);
        return;
      }
      const { code } = await deleteAudioResource({ id });
      if (code === 200) {
        this.list.splice(index, 1);
      } else {
        this.$message.error('删除失败请重试');
      }
    },
    async checkFileHandler(evt) {
      const acceptMimeTyep = [
        'audio/mpeg',
        'audio/mp3',
        'audio/ogg',
        'audio/wav'
      ];
      const file = evt.target.files[0];
      if (acceptMimeTyep.indexOf(file.type) === -1) {
        this.$message.error('所选文件格式不支持 (｀・ω・´) ');
        return;
      }
      const formData = {
        name: file.name.slice(0, file.name.lastIndexOf('.')),
        suffix: file.name.slice(file.name.lastIndexOf('.') + 1),
        size: file.size,
        mime: file.type,
        sign: `${Date.now()}-${CryptoJS.SHA256(`${Date.now()}`).toString()}`,
        progress: 0,
        isComplete: true,
        isUploading: true
      };
      evt.target.value = null;
      await this.dispachEventUploading(true);
      await this.uploadHandler({ file, formData });
    },
    async uploadHandler({ file, formData }) {
      try {
        this.list.push(formData);
        // 调用这个方法就可以生成一个oss实例
        const client = await generateOSS();
        const dir = 'audio/' + formData.suffix;
        const name = `-${formData.sign}.${formData.suffix}`;
        // 这个是初始排序
        formData.p = this.list.length;
        formData.ossClinet = client;
        const res_upload = await client.multipartUpload(dir + name, file, {
          progress: p => {
            formData.progress = Number(parseInt(p * 10000)) / 100;
          }
        });
        formData.url = res_upload.name;
        formData.isUploading = false;
        await this.saveUploadHandler(formData);
      } catch (error) {
        if (error.name === 'cancel') {
          this.$message.error('上传已取消');
        }
      }
    },
    async saveUploadHandler(element) {
      const res_create = await createAudioResource({
        aid: this.aid,
        ...element
      });
      if (res_create.code !== 200) {
        this.$message.error('文件上传出错,请重试');
        element.isComplete = false;
        return;
      }
      element.id = res_create.data.res_audio.id;
      element.uploading = false;
      this.dispachEventUploading(false);
    },
    async dispachEventUploading(boolean) {
      if (boolean) { // 这里还是早就想到了要所有任务上传完成...
        this.uploading.push(0);
      } else {
        this.uploading.shift();
      }
      this.$emit('uploading', this.uploading.length !== 0);
    },
    async editInfoHandler(element) {
      this.isEdit = true;
      const { id, name, isUploading } = element;
      if (isUploading) {
        this.isEdit = false;
        return;
      }
      const data = {
        title: name
      };
      const res = await editAudioResource({ id, data });
      this.$message({
        type: res.code === 200 ? 'success' : 'warning',
        message: res.message
      });
      this.isEdit = false;
    }
  }
};
</script>

<style lang="scss" scoped>
@import '~@/styles/variables.scss';

.container-item-upload {
  .item-upload {
    margin: 20px 0;
    padding: 10px 0;
    display: flex;
    align-items: center;
    position: relative;
    border: 1px solid $tagBorderColor;
    border-radius: 5px;
    border-top-left-radius: 0;
    cursor: move;
    cursor: -webkit-grabbing;
  }
  .item-p {
    position: absolute;
    top: -1px;
    right: calc(100%);
  }
  .item-info {
    width: 100%;
    margin-left: 10px;
  }
  .item-title {
    display: inline-block;
    font-size: 14px;
    height: 16px;
  }
  .item-music-icon {
    display: block;
    width: 69px;
    height: 44px;
    font-size: 14px;
    color: #222;
    line-height: 44px;
    background: url()
      21px no-repeat;
  }
  .item-delete {
    position: absolute;
    top: 10px;
    right: 30px;
    color: $bilipink;
  }
  .item-edit {
    position: absolute;
    bottom: 10px;
    right: 30px;
    color: $menuActiveText;
  }
  .item-reupload {
    position: absolute;
    bottom: 10px;
    right: 100px;
    color: $bilipink;
  }
  .item-upload-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 40px;
    border: 2px dashed #ccd0d7;
    border-radius: 4px;
    background-size: 100% 100%;
    background-repeat: no-repeat;
    position: relative;
    text-align: center;
    cursor: pointer;
    font-size: 14px;
    color: #6d757a;
  }
  .item-progress {
    display: flex;
    align-items: center;
    padding-right: 10px;
  }
  .item-upload-input {
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 3;
    display: block;
    opacity: 0;
    cursor: pointer;
  }
}
</style>
